package view;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.Observable;
import java.util.Observer;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import model.FileParser;
import model.Manuscript;
import model.Review;
import model.State;

/**
 * Panel specific to user type Author. Shows all papers 
 * submitted by authors, and reviews completed by reviewers.
 * @author Sarah George
 */
@SuppressWarnings("serial")
public class AuthorPanel extends JPanel implements Observer {
	
	/**
	 * Current state of user, including user id, conference,
	 * and role.
	 */
	private State my_state;
	
	/**
	 * Final array of Strings that hold the titles for each column.
	 */
	private static final String[] headTitles = new String[] { "Title", "Open", "Edit", "Delete", "Reviews" };
	
	/**
	 * Final int that holds the length of the array of column titles.
	 */
	private static final int cols = headTitles.length;
	
	/**
	 * File parser object.
	 */
	private FileParser my_fp;
	
	/**
	 * Papers associated with a conference.
	 */
	private Manuscript[] my_papers;
	
	/**
	 * Constructor for an author panel.
	 * @param the_state the current state of the system.
	 */
	public AuthorPanel(State the_state) {
		super();
		my_state = the_state;
		my_fp = my_state.getParser();
		my_fp.addObserver(this);
		setup();
	}

	/**
	 * Method to setup the author panel.
	 */
	public void setup() {
		GridLayout exp_layout = new GridLayout(0,cols);
		this.setLayout(exp_layout);
		int user_id = my_state.getUser().getID();
		int conf_id = my_state.getConference().getConfID();
		my_papers = my_fp.getPapersByAuthor(user_id, conf_id);
		
		int paperCount = my_papers.length;
		
		
		//CREATE THE ARRAYS OF LABELS AND BUTTONS AND SUCH
		JLabel[] titles = new JLabel[paperCount];		
		JButton[] openButton = new JButton[paperCount];
		JButton[] editButton = new JButton[paperCount];
		JButton[] deleteButton = new JButton[paperCount];
		ArrayList<JComboBox<Review>> reviewBoxes = new ArrayList<JComboBox<Review>>();
		
		//PREPARE OBJECTS TO DRAW
		if (my_papers.length > 0) //draw headers
		{
			JLabel[] headers = new JLabel[cols];
			for(int i = 0; i < cols; i++)
			{
				headers[i] = new JLabel(headTitles[i]);
				headers[i].setHorizontalAlignment(JLabel.CENTER);
				add(headers[i]);
			}
		}
		
		for (int i = 0; i < my_papers.length; i++) {
			titles[i] = new JLabel(my_papers[i].getMy_title());
			openButton[i] = new JButton(new OpenPaperAction(my_papers[i]));
			editButton[i] = new JButton(new EditAction(my_papers[i]));			
			deleteButton[i] = new JButton(new DeleteAction(my_papers[i]));
			reviewBoxes.add(buildComboBox(my_papers[i]));
		}
		
		//DRAW THEM ON THE PAGE
		for(int i=0; i < paperCount; i++)
		{
			add(titles[i]);
			add(openButton[i]);
			add(editButton[i]);
			add(deleteButton[i]);
			add(reviewBoxes.get(i));
			
			//only enable the review box if the paper is rejected or accepted.
			if (my_papers[i].getMy_status().ordinal() < 4)
				reviewBoxes.get(i).setEnabled(false);
			
		}
			
		//AFTER ALL PAPERS ARE DRAWN, SHOW THE USER THE OPTION TO CREATE A NEW PAPER
		JButton addNew = new JButton(new NewAction());
		add(addNew);
		Date rightNow = new Date();
		if (rightNow.compareTo(my_state.getConference().getSubmissionDL()) > 0 ||
			my_papers.length >= 4)
		{
			addNew.setEnabled(false);
		}
	}
	
	/**
	 * Method to remove everything from the panel. 
	 */
	public void clear()
	{
		this.removeAll();
		this.repaint();
	}
	
	/**
	 * Method to update the panel.
	 * @param o the observable being watched by this observer
	 * @param arg the object that called notify observers.
	 */
	@Override
	public void update(Observable o, Object arg) {
		this.clear();
		this.setup();
		this.validate();
		this.repaint();
	}

	/**
	 * Method to build a review combobox for a specific manuscript.
	 * @param manuscript the specific manuscript.
	 * @return the combobox of reviews for the manuscript.
	 */
	private JComboBox<Review> buildComboBox(Manuscript manuscript) {
		//GET THE REVIEWS FOR THE PAPER AND
		//ADD THEM AS ITEMS TO THE COMBO BOX
		Review[] reviews = my_state.getParser().getReviewsByPaperID(manuscript.getMy_id());
		JComboBox<Review> toReturn = new JComboBox<Review>();
		for (Review r : reviews)
		{
			toReturn.addItem(r);
		}
		
		toReturn.addActionListener(new ReviewAction());
		
		return toReturn;
	}


	/**
	 * Class to create an edit action.
	 * @author Kevin Anderson
	 * @version 12/5/2012
	 */
	private class EditAction extends AbstractAction {

		/**
		 * The manuscript to be edited.
		 */
		private Manuscript my_manuscript;

		/**
		 * Constructor for edit action.
		 * @param the_manuscript the manuscript to be edited.
		 */
		public EditAction(Manuscript the_manuscript)
		{
		    super("Modify");
		    putValue(Action.MNEMONIC_KEY, KeyEvent.VK_M);
		    putValue(Action.SELECTED_KEY, true);			
			my_manuscript = the_manuscript;
		}

		/**
		 * Method to edit the manuscript.
		 * @param e the action event that triggers the method.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			EditPaperFrame editFrame = new EditPaperFrame(my_manuscript, my_state);
			editFrame.setup();
		}		
	}//End class edit action
	
	
	/**
	 * Class to delete an existing manuscript.
	 * @author Sarah George, Kevin Anderson
	 * @version Autumn 2012
	 */
	@SuppressWarnings("serial")
	private class DeleteAction extends AbstractAction {
		
		/**
		 * Field to hold the manuscript.
		 */
		private Manuscript paper;
		
		/**
		 * Constructor for a delete action.
		 * @param the_paper the paper to be deleted.
		 */
		public DeleteAction(Manuscript the_paper) {
			super("Delete Paper");
		    putValue(Action.MNEMONIC_KEY, KeyEvent.VK_D);
		    putValue(Action.SELECTED_KEY, true);
		    paper = the_paper;
		}

		/**
		 * Method to remove a paper.
		 * @param e the action event that triggers the method.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			my_state.getParser().removeManuscript(paper);
		}
	}//End class delete action.
	

	/**
	 * Class to open a selected review.
	 * @author Sarah George, Kevin Anderson
	 * @version 12/5/2012
	 */
	private class ReviewAction implements ActionListener {
		
		/**
		 * Method to open the selected review.
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			
			if (e.getSource() instanceof JComboBox<?>)
			{
				JComboBox<Review> cb = (JComboBox<Review>)e.getSource();
				Review rev = (Review)cb.getSelectedItem();
				rev.open();
			}
		}
	}//End class review action.
	
	
	/**
	 * Class to create the JFrame and panel to submit a new paper.
	 * @author Sarah George, Kevin Anderson
	 * @version 12/5/2012
	 */
	@SuppressWarnings("serial")
	private class NewAction extends AbstractAction {
		
		 /**
		   * Constructs a new paper action.
		   */
		  public NewAction() {
		    super("Submit new paper ...");
		    putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
		    putValue(Action.SELECTED_KEY, true);
		  }

		/**
		 * Method to create the JFrame and JPanel for adding a new paper.
		 * @param arg0 the action event that triggers this method.
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) {
			JFrame new_paper_frame = new JFrame("Submit New Paper");
			NewPaperPanel npp = new NewPaperPanel(my_state, new_paper_frame);
			
			new_paper_frame.add(npp,BorderLayout.CENTER);
			new_paper_frame.setResizable(true); 
			new_paper_frame.pack();
			new_paper_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
			new_paper_frame.setLocationRelativeTo(null);
			new_paper_frame.setVisible(true);
		}

	}//End class new action.
}//End class Author panel.